﻿using Microsoft.Extensions.DependencyInjection;
using System;
using System.Reflection;

namespace RoslynProxy.Core
{
    /// <summary>
    /// Roslyn 代理基类
    /// </summary>
    /// <typeparam name="TProxyService">代理服务类型</typeparam>
    /// <typeparam name="TService">代理接口</typeparam>
    /// <typeparam name="TImplementation">代理接口的实例类型</typeparam>
    public abstract class RoslynDispatchProxy<TProxyService, TService, TImplementation> : DispatchProxy
        where TService : class
        where TProxyService : RoslynDispatchProxy<TProxyService, TService, TImplementation>
        where TImplementation : TService
    {
        protected TService TargetService { get; private set; } = null!;

        protected IServiceProvider ServiceProvider { get; private set; } = null!;

        /// <summary>
        /// 获取代理服务
        /// </summary>
        public static TService GetProxyService(IServiceProvider serviceProvider)
        {
            // 创建代理服务
            var proxyService = Create<TService, TProxyService>();

            if (proxyService is TProxyService dispatchProxy)
            {
                dispatchProxy.ServiceProvider = serviceProvider;
                dispatchProxy.TargetService = serviceProvider.GetRequiredService<TImplementation>();
            }

            return proxyService;
        }

        // 覆写 Invoke 方法来处理方法调用  
        protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
        {
            if (targetMethod != null)
            {
                // 检查是否是属性的 getter 或 setter  
                if (targetMethod.IsSpecialName && (targetMethod.Name.StartsWith("get_") || targetMethod.Name.StartsWith("set_")))
                {
                    // 调用目标对象上的 getter 或 setter  
                    return targetMethod.Invoke(TargetService, args);
                }
                else
                {
                    BeginInvoke();
                    // 调用目标对象上的方法  
                    var result = targetMethod.Invoke(TargetService, args);
                    EndInvoke();

                    return result;
                }
            }

            return null;
        }

        /// <summary>
        /// 开始调用前
        /// </summary>
        protected abstract void BeginInvoke();

        /// <summary>
        /// 调用完成后
        /// </summary>
        protected abstract void EndInvoke();
    }
}
